﻿using System;
using System.Text;
namespace NFinal.Sql.Like
{
    public class LikeEncoding
    {
        LikeEncodeKey key;
        public LikeEncoding(LikeEncodeKey likeEncodeKey)
        {
            this.key = likeEncodeKey;
        }
        public  byte Encrypt(byte data, int byteCount, int highBitsToKeep = 1)
        {
            if (byteCount == 1)
            {
                if (data < 32 || data == 127 || data=='%' || data=='_')
                {
                    return data;
                }
                else
                {
                    return (byte)(key.enOneByteDic[data - 32] + 32);
                }
            }
            else
            {
                if (highBitsToKeep == 2)
                {
                    return (byte)(key.en6BitDic[data & 0x3f] | 0x80);
                }
                else if (highBitsToKeep == 3)
                {
                    return (byte)(key.en5BitDic[data & 0x1f] | 0xc0);
                }
                else if (highBitsToKeep == 4)
                {
                    return (byte)(key.en4BitDic[data & 0x0f] | 0xe0);
                }
                else if (highBitsToKeep == 5)
                {
                    return (byte)(key.en3BitDic[data & 0x07] | 0xf0);
                }
                else if (highBitsToKeep == 6)
                { 
                    return (byte)(key.en2BitDic[data & 0x03] | 0xf8);
                }
                else
                {
                    return 0;
                }
            }
        }
        public byte Decrypt(byte data, int byteCount, int highBitsToKeep = 1)
        {
            if (byteCount == 1)
            {
                if (data < 32 || data == 127 || data=='%' || data=='_')
                {
                    return data;
                }
                else
                {
                    return (byte)(key.deOneByteDic[data - 32] + (byte)32);
                }
            }
            else
            {
                if (highBitsToKeep == 2)
                {
                    return (byte)(key.de6BitDic[data & (byte)0x3f] | (byte)0x80);
                }
                else if (highBitsToKeep == 3)
                {
                    return (byte)(key.de5BitDic[data & (byte)0x1f] | 0xc0);
                }
                else if (highBitsToKeep == 4)
                {
                    return (byte)(key.de4BitDic[data & (byte)0x0f] | 0xe0);
                }
                else if (highBitsToKeep == 5)
                {
                    return (byte)(key.de3BitDic[data & (byte)0x07] | 0xf0);
                }
                else if (highBitsToKeep == 6)
                {
                    return (byte)(key.de2BitDic[data & (byte)0x03] | 0xf8);
                }
                else
                {
                    return 0;
                }
            }
        }

        public string UTF8En(string text)
        {
            byte[] buffer = System.Text.Encoding.UTF8.GetBytes(text);
            byte[] values = new byte[buffer.Length];
            byte[] unicode = new byte[4];
            int i = 0;
            while (i < buffer.Length)
            {
                byte byte1 = buffer[i];
                int bytes_count = 0;
                if ((byte1 & 0x80) == 0)
                {
                    bytes_count = 1;
                    values[i] = Encrypt(buffer[i], 1, 1);
                    unicode[4] = buffer[i];
                    //values[i] = buffer[i];
                }
                else if ((byte1 & 0xe0) == 0xc0)
                {
                    bytes_count = 2;
                    //values[i] = buffer[i];
                    values[i] = Encrypt(buffer[i], 2, 3);
                    //values[i+1] = buffer[i+1];
                    values[i + 1] = Encrypt(buffer[i + 1], 2, 2);
                }
                else if ((byte1 & 0xf0) == 0xe0)
                {
                    bytes_count = 3;
                    //values[i] = buffer[i];
                    values[i] = Encrypt(buffer[i], 3, 4);
                    //values[i+1] = buffer[i+1];
                    values[i + 1] = Encrypt(buffer[i + 1], 3, 2);
                    //values[i+2] = buffer[i+2];
                    values[i + 2] = Encrypt(buffer[i + 2], 3, 2);
                }
                else if ((byte1 & 0xf8) == 0xf0)
                {
                    bytes_count = 4;
                    //values[i] = buffer[i];
                    values[i] = Encrypt(buffer[i], 4, 5);
                    //values[i+1] = buffer[i+1];
                    values[i + 1] = Encrypt(buffer[i + 1], 4, 2);
                    //values[i+2] = buffer[i+2];
                    values[i + 2] = Encrypt(buffer[i + 2], 4, 2);
                    //values[i+3] = buffer[i+3];
                    values[i + 3] = Encrypt(buffer[i + 3], 4, 2);
                }
                else if ((byte1 & 0xfc) == 0xf8)
                {
                    bytes_count = 5;
                    values[i] = Encrypt(buffer[i], 5, 6);
                    //values[i+1] = buffer[i+1];
                    values[i + 1] = Encrypt(buffer[i + 1], 4, 2);
                    //values[i+2] = buffer[i+2];
                    values[i + 2] = Encrypt(buffer[i + 2], 4, 2);
                    //values[i+3] = buffer[i+3];
                    values[i + 3] = Encrypt(buffer[i + 3], 4, 2);
                    //values[i+4] = buffer[i+4];
                    values[i + 4] = Encrypt(buffer[i + 4], 4, 2);
                }
                else if ((byte1 & 0xfe) == 0xfc)
                {
                    bytes_count = 6;
                    values[i] = Encrypt(buffer[i], 6, 7);
                    //values[i+1] = buffer[i+1];
                    values[i + 1] = Encrypt(buffer[i + 1], 4, 2);
                    //values[i+2] = buffer[i+2];
                    values[i + 2] = Encrypt(buffer[i + 2], 4, 2);
                    //values[i+3] = buffer[i+3];
                    values[i + 3] = Encrypt(buffer[i + 3], 4, 2);
                    //values[i+4] = buffer[i+4];
                    values[i + 4] = Encrypt(buffer[i + 4], 4, 2);
                }
                else
                {
                    return null;
                }
                i += bytes_count;
            }
            string value = System.Text.Encoding.UTF8.GetString(values);
            return value;
        }

        public string UTF8De(string text)
        {
            byte[] buffer = System.Text.Encoding.UTF8.GetBytes(text);
            byte[] values = new byte[buffer.Length];
            int i = 0;
            while (i < buffer.Length)
            {
                byte byte1 = buffer[i];
                int bytes_count = 0;
                if ((byte1 & 0x80) == 0)
                {
                    bytes_count = 1;
                    //values[i] = buffer[i];
                    values[i] = Decrypt(buffer[i], 1, 1);
                }
                else if ((byte1 & 0xe0) == 0xc0)
                {
                    bytes_count = 2;
                    //values[i] = buffer[i];
                    values[i] = Decrypt(buffer[i], 2, 3);
                    //values[i+1] = buffer[i+1];
                    values[i + 1] = Decrypt(buffer[i + 1], 2, 2);
                }
                else if ((byte1 & 0xf0) == 0xe0)
                {
                    bytes_count = 3;
                    //values[i] = buffer[i];
                    values[i] = Decrypt(buffer[i], 3, 4);
                    //values[i+1] = buffer[i+1];
                    values[i + 1] = Decrypt(buffer[i + 1], 3, 2);
                    //values[i+2] = buffer[i+2];
                    values[i + 2] = Decrypt(buffer[i + 2], 3, 2);
                }
                else if ((byte1 & 0xf8) == 0xf0)
                {
                    bytes_count = 4;
                    //values[i] = buffer[i];
                    values[i] = Decrypt(buffer[i], 4, 5);
                    //values[i+1] = buffer[i+1];
                    values[i + 1] = Decrypt(buffer[i + 1], 4, 2);
                    //values[i+2] = buffer[i+2];
                    values[i + 2] = Decrypt(buffer[i + 2], 4, 2);
                    //values[i+3] = buffer[i+3];
                    values[i + 3] = Decrypt(buffer[i + 3], 4, 2);
                }
                else
                {
                    return null;
                }
                i += bytes_count;
            }
            string value = System.Text.Encoding.UTF8.GetString(values);
            return value;
        }
    }
}
